package com.superhero.miniprogram.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.superhero.common.Enum.RoleType;
import com.superhero.common.constant.Constant;
import com.superhero.common.exception.BusinessException;
import com.superhero.common.pojo.ApiResult;
import com.superhero.common.pojo.WxLoginInput;
import com.superhero.common.pojo.entity.AuthUser;
import com.superhero.common.pojo.vo.WxLoginOutput;
import com.superhero.common.repository.AuthUserRepository;
import com.superhero.common.utils.OptionalUtil;
import com.superhero.miniprogram.config.WxConfiguration;
import com.superhero.miniprogram.config.WxProperties;
import com.superhero.miniprogram.security.JwtTokenUtils;
import com.superhero.miniprogram.security.UserUtil;
import com.superhero.miniprogram.service.LoginService;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Optional;

@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    WxProperties properties;
    @Resource
    JwtTokenUtils jwtTokenUtils;
    @Resource
    BCryptPasswordEncoder passwordEncoder;

    @Resource
    AuthUserRepository authUserRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<WxLoginOutput> wxLogin(WxLoginInput input) throws WxErrorException {
        final WxMaService wxService = WxConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
        WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(input.getCode());

        WxLoginOutput output = new WxLoginOutput();
        String token = null;
        // 检查用户是否已注册
        Optional<AuthUser> authUser = authUserRepository.findAuthUserByWxOpenId(session.getOpenid());
        // 未注册创建新的用户，身份为未认证用户
        if (!authUser.isPresent()) {
            // 获取微信用户基本信息
            WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(session.getSessionKey(), input.getEncryptedData(), input.getIv());
            AuthUser newUser = new AuthUser();
            newUser.setUsername(userInfo.getNickName())
                    .setWxOpenId(session.getOpenid())
                    .setAvatarUrl(userInfo.getAvatarUrl())
                    .setUnionId(session.getUnionid())
                    .setRole(RoleType.UNCERTIFICATION.ordinal())
                    .setLocked(Constant.NO);
            authUserRepository.saveAndFlush(newUser);
            token = jwtTokenUtils.generateToken(newUser);
            output.setId(newUser.getId())
                    .setUsername(newUser.getUsername())
                    .setAvatarUrl(newUser.getAvatarUrl())
                    .setRole(RoleType.UNCERTIFICATION.ordinal())
                    .setToken(token);
        } else {
            if (authUser.get().getLocked().equals(Constant.YES)) {
                throw new BusinessException("您的账号已被锁定，请联系管理员了解详情");
            }
            token = jwtTokenUtils.generateToken(authUser.get());
            output.setId(authUser.get().getId())
                    .setUsername(authUser.get().getUsername())
                    .setAvatarUrl(authUser.get().getAvatarUrl())
                    .setRole(authUser.get().getRole())
                    .setToken(token);
        }
        return ApiResult.success(output);
    }

    @Override
    public ApiResult<WxLoginOutput> normalLogin(String username, String password) {
        Optional<AuthUser> user = authUserRepository.findAuthUserByUsername(username);
        if (!user.isPresent()) {
            throw new BusinessException("用户不存在");
        }
        boolean isMatch = passwordEncoder.matches(password, user.get().getPassword());
        if (!isMatch) {
            throw new BusinessException("密码错误");
        }
        if (!user.get().getRole().equals(RoleType.INSPECTOR.ordinal())) {
            throw new BusinessException("您的账号没有检查人员权限，请重试");
        }
        if (user.get().getLocked().equals(Constant.YES)) {
            throw new BusinessException("您的账号已被锁定，请联系管理员了解详情");
        }
        WxLoginOutput output = new WxLoginOutput();
        String token = jwtTokenUtils.generateToken(user.get());
        output.setUsername(user.get().getUsername())
                .setAvatarUrl(user.get().getAvatarUrl())
                .setRole(user.get().getRole())
                .setToken(token);
        return ApiResult.success(output);
    }

    @Override
    public void changePassword(String oldPassword, String newPassword) {
        String username = UserUtil.getUserUsername();
        AuthUser authUser = OptionalUtil.get(authUserRepository.findAuthUserByUsername(username));
        boolean isMatch = passwordEncoder.matches(oldPassword, authUser.getPassword());
        if (!isMatch) {
            throw new BusinessException("您输入的旧密码错误！");
        }
        authUser.setPassword(passwordEncoder.encode(newPassword));
        authUserRepository.saveAndFlush(authUser);
    }
}
